/*
 * PrintPreviewPanel.java 27 aout 07
 *
 * Sweet Home 3D, Copyright (c) 2007 Emmanuel PUYBARET / eTeks <info@eteks.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.eteks.sweethome3d.swing;

import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.Locale;

import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.border.AbstractBorder;

import com.eteks.sweethome3d.model.Home;
import com.eteks.sweethome3d.model.UserPreferences;
import com.eteks.sweethome3d.tools.OperatingSystem;
import com.eteks.sweethome3d.viewcontroller.DialogView;
import com.eteks.sweethome3d.viewcontroller.HomeController;
import com.eteks.sweethome3d.viewcontroller.PrintPreviewController;
import com.eteks.sweethome3d.viewcontroller.View;

/**
 * Home print preview editing panel.
 * @author Emmanuel Puybaret
 */
public class PrintPreviewPanel extends JPanel implements DialogView
{
	private enum ActionType
	{
		SHOW_PREVIOUS_PAGE, SHOW_NEXT_PAGE
	}
	
	private final UserPreferences preferences;
	private JToolBar toolBar;
	private HomePrintableComponent printableComponent;
	private JLabel pageLabel;
	
	/**
	 * Creates a panel that displays print preview.
	 * @param home home previewed by this panel
	 * @param preferences the user preferences from which localized data is retrieved
	 * @param homeController the controller of <code>home</code>
	 * @param printPreviewController the controller of this panel
	 */
	public PrintPreviewPanel(Home home, UserPreferences preferences, HomeController homeController,
			PrintPreviewController printPreviewController)
	{
		super(new ProportionalLayout());
		this.preferences = preferences;
		createActions(preferences);
		installKeyboardActions();
		createComponents(home, homeController);
		layoutComponents();
		updateComponents();
	}
	
	/**
	 * Creates actions.  
	 */
	private void createActions(UserPreferences preferences)
	{
		// Show previous page action
		Action showPreviousPageAction = new ResourceAction(preferences, PrintPreviewPanel.class,
				ActionType.SHOW_PREVIOUS_PAGE.name())
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				printableComponent.setPage(printableComponent.getPage() - 1);
				updateComponents();
			}
		};
		// Show next page action
		Action showNextPageAction = new ResourceAction(preferences, PrintPreviewPanel.class,
				ActionType.SHOW_NEXT_PAGE.name())
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				printableComponent.setPage(printableComponent.getPage() + 1);
				updateComponents();
			}
		};
		ActionMap actionMap = getActionMap();
		actionMap.put(ActionType.SHOW_PREVIOUS_PAGE, showPreviousPageAction);
		actionMap.put(ActionType.SHOW_NEXT_PAGE, showNextPageAction);
	}
	
	/**
	 * Installs keys bound to actions. 
	 */
	private void installKeyboardActions()
	{
		InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
		inputMap.put(KeyStroke.getKeyStroke("LEFT"), ActionType.SHOW_PREVIOUS_PAGE);
		inputMap.put(KeyStroke.getKeyStroke("UP"), ActionType.SHOW_PREVIOUS_PAGE);
		inputMap.put(KeyStroke.getKeyStroke("PAGE_UP"), ActionType.SHOW_PREVIOUS_PAGE);
		inputMap.put(KeyStroke.getKeyStroke("RIGHT"), ActionType.SHOW_NEXT_PAGE);
		inputMap.put(KeyStroke.getKeyStroke("DOWN"), ActionType.SHOW_NEXT_PAGE);
		inputMap.put(KeyStroke.getKeyStroke("PAGE_DOWN"), ActionType.SHOW_NEXT_PAGE);
	}
	
	/**
	 * Creates and initializes components.
	 */
	private void createComponents(Home home, HomeController homeController)
	{
		this.printableComponent = new HomePrintableComponent(home, homeController, getFont());
		this.printableComponent.setBorder(BorderFactory.createCompoundBorder(new AbstractBorder()
		{
			@Override
			public Insets getBorderInsets(Component c)
			{
				return new Insets(0, 0, 5, 5);
			}
			
			@Override
			public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
			{
				Graphics2D g2D = (Graphics2D) g;
				Color oldColor = g2D.getColor();
				// Fill left and right border with a gradient
				for (int i = 0; i < 5; i++)
				{
					g2D.setColor(new Color(128, 128, 128, 200 - i * 45));
					g2D.drawLine(x + width - 5 + i, y + i, x + width - 5 + i, y + height - 5 + i);
					g2D.drawLine(x + i, y + height - 5 + i, x + width - 5 + i - 1, y + height - 5 + i);
				}
				g2D.setColor(oldColor);
			}
		}, BorderFactory.createLineBorder(Color.BLACK)));
		
		this.pageLabel = new JLabel();
		
		this.toolBar = new JToolBar()
		{
			public void applyComponentOrientation(ComponentOrientation orientation)
			{
				// Ignore orientation 
			}
		};
		this.toolBar.setFloatable(false);
		ActionMap actions = getActionMap();
		if (OperatingSystem.isMacOSXLeopardOrSuperior() && OperatingSystem.isJavaVersionGreaterOrEqual("1.7"))
		{
			// Add buttons with higher insets to ensure the top and bottom of segmented buttons are correctly drawn
			class HigherInsetsButton extends JButton
			{
				public HigherInsetsButton(Action action)
				{
					super(action);
				}
				
				@Override
				public Insets getInsets()
				{
					Insets insets = super.getInsets();
					insets.top += 3;
					insets.bottom += 3;
					return insets;
				}
			}
			toolBar.add(new HigherInsetsButton(actions.get(ActionType.SHOW_PREVIOUS_PAGE)));
			toolBar.add(new HigherInsetsButton(actions.get(ActionType.SHOW_NEXT_PAGE)));
		}
		else
		{
			this.toolBar.add(actions.get(ActionType.SHOW_PREVIOUS_PAGE));
			this.toolBar.add(actions.get(ActionType.SHOW_NEXT_PAGE));
		}
		updateToolBarButtonsStyle(this.toolBar);
		
		this.toolBar.add(Box.createHorizontalStrut(20));
		this.toolBar.add(this.pageLabel);
		
		// Remove focusable property on buttons
		for (int i = 0, n = toolBar.getComponentCount(); i < n; i++)
		{
			toolBar.getComponentAtIndex(i).setFocusable(false);
		}
	}
	
	/**
	 * Under Mac OS X 10.5 use segmented buttons with properties 
	 * depending on toolbar orientation.
	 */
	private void updateToolBarButtonsStyle(JToolBar toolBar)
	{
		// Use segmented buttons under Mac OS X 10.5
		if (OperatingSystem.isMacOSXLeopardOrSuperior())
		{
			// Retrieve component orientation because Mac OS X 10.5 miserably doesn't it take into account 
			JComponent previousButton = (JComponent) toolBar.getComponentAtIndex(0);
			previousButton.putClientProperty("JButton.buttonType", "segmentedTextured");
			previousButton.putClientProperty("JButton.segmentPosition", "first");
			JComponent nextButton = (JComponent) toolBar.getComponentAtIndex(1);
			nextButton.putClientProperty("JButton.buttonType", "segmentedTextured");
			nextButton.putClientProperty("JButton.segmentPosition", "last");
		}
	}
	
	/**
	 * Layouts panel components in panel with their labels. 
	 */
	private void layoutComponents()
	{
		// Add toolbar at top in a flow layout panel to make it centered
		JPanel panel = new JPanel();
		panel.add(this.toolBar);
		add(panel, ProportionalLayout.Constraints.TOP);
		// Add printable component at bottom of proportional layout panel
		add(this.printableComponent, ProportionalLayout.Constraints.BOTTOM);
	}
	
	/**
	 * Updates components.
	 */
	private void updateComponents()
	{
		ActionMap actions = getActionMap();
		actions.get(ActionType.SHOW_PREVIOUS_PAGE).setEnabled(this.printableComponent.getPage() > 0);
		actions.get(ActionType.SHOW_NEXT_PAGE)
				.setEnabled(this.printableComponent.getPage() < this.printableComponent.getPageCount() - 1);
		this.pageLabel.setText(preferences.getLocalizedString(PrintPreviewPanel.class, "pageLabel.text",
				this.printableComponent.getPage() + 1, this.printableComponent.getPageCount()));
	}
	
	/**
	 * Displays this panel in a modal resizable dialog box. 
	 */
	public void displayView(View parentView)
	{
		String dialogTitle = preferences.getLocalizedString(PrintPreviewPanel.class, "printPreview.title");
		JOptionPane optionPane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION);
		if (parentView != null)
		{
			optionPane.setComponentOrientation(((JComponent) parentView).getComponentOrientation());
		}
		JDialog dialog = optionPane.createDialog(SwingUtilities.getRootPane((JComponent) parentView), dialogTitle);
		dialog.applyComponentOrientation(ComponentOrientation.getOrientation(Locale.getDefault()));
		dialog.setResizable(true);
		// Pack again because resize decorations may have changed dialog preferred size
		dialog.pack();
		dialog.setMinimumSize(dialog.getPreferredSize());
		dialog.setVisible(true);
		dialog.dispose();
	}
}
